import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.ImageObserver;
import java.util.Random;

/**
 * 窗体类
 * ======================================
 * USER NAME: ving <904679843@qq.com>
 * DATE TIME: 17-9-10 下午7:35
 * ======================================
 */
public class TspFrame extends JFrame implements ActionListener {

    private double[] x;
    private double[] y;
    private String[] n;

    private int[] bestPath;
    private int bestLength;
    private double[][] distance;

    private double zoom = 3;
    private int left = 10;
    private int top = 35;

    private Image image;

    private int width;
    private int height;

    private boolean isDrawLine;

    private City city;

    private JLabel labelParamSet;
    private JLabel labelCalcuSet;
    private JLabel labelResultShow;
    private JLabel labelMessageShow;

    private JLabel labelSpeed;
    private JLabel labelInitTp;
    private JLabel labelMinsTp;
    private JLabel labelIteration;

    private JTextField textSpeed;
    private JTextField testInitTp;
    private JTextField testlMinsTp;
    private JTextField textIteration;

    private JLabel labelStartCity;
    private JComboBox boxStartCity;

    private JLabel labelUsedTime;
    private JLabel labelBestLength;
    private JLabel labelMessage;

    private JButton buttonCalculation;


    public TspFrame(City city) {
        this.city = city;
        this.isDrawLine = false;
        this.x = city.getX();
        this.y = city.getY();
        this.n = city.getCity();
        this.distance = city.getDistance();

        //======================================================================
        image = new ImageIcon(Toolkit.getDefaultToolkit().getImage("resource/k.jpg")).getImage();
        width = (int) (image.getWidth(null) / zoom);
        height = (int) (image.getHeight(null) / zoom);

        //======================================================================
        this.setTitle("城市遍历");
        this.setSize(width + 220, height + 40);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setLayout(null);
        this.setResizable(false);

        //======================================================================
        labelParamSet = new JLabel("参数设置");
        labelParamSet.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelParamSet.setBounds(width + left * 2 + 40, 10, 100, 25);
        this.add(labelParamSet);

        labelSpeed = new JLabel("退火速度：");
        labelSpeed.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelSpeed.setBounds(width + left * 2, 40, 100, 25);
        this.add(labelSpeed);

        textSpeed = new JTextField();
        textSpeed.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        textSpeed.setBounds(width + left * 2 + 80, 40, 100, 25);
        textSpeed.setText("0.98");
        this.add(textSpeed);

        labelInitTp = new JLabel("初始温度：");
        labelInitTp.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelInitTp.setBounds(width + left * 2, 70, 100, 25);
        this.add(labelInitTp);

        testInitTp = new JTextField();
        testInitTp.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        testInitTp.setBounds(width + left * 2 + 80, 70, 100, 25);
        testInitTp.setText("1000");
        this.add(testInitTp);

        labelMinsTp = new JLabel("最低温度：");
        labelMinsTp.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelMinsTp.setBounds(width + left * 2, 100, 100, 25);
        this.add(labelMinsTp);

        testlMinsTp = new JTextField();
        testlMinsTp.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        testlMinsTp.setBounds(width + left * 2 + 80, 100, 100, 25);
        testlMinsTp.setText("0.001");
        this.add(testlMinsTp);

        labelIteration = new JLabel("迭代次数：");
        labelIteration.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelIteration.setBounds(width + left * 2, 130, 100, 25);
        this.add(labelIteration);

        textIteration = new JTextField();
        textIteration.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        textIteration.setBounds(width + left * 2 + 80, 130, 100, 25);
        textIteration.setText("5000");
        this.add(textIteration);

        //======================================================================
        labelCalcuSet = new JLabel("计算设置");
        labelCalcuSet.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelCalcuSet.setBounds(width + left * 2 + 40, 170, 100, 25);
        this.add(labelCalcuSet);

        labelStartCity = new JLabel("起始城市：");
        labelStartCity.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelStartCity.setBounds(width + left * 2, 200, 100, 25);
        this.add(labelStartCity);

        boxStartCity = new JComboBox(city.getCity());
        boxStartCity.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        boxStartCity.setBounds(width + left * 2 + 80, 200, 80, 25);
        this.add(boxStartCity);

        //======================================================================
        labelResultShow = new JLabel("结果显示");
        labelResultShow.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelResultShow.setBounds(width + left * 2 + 40, 240, 300, 25);
        this.add(labelResultShow);

        labelUsedTime = new JLabel("计算用时：");
        labelUsedTime.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelUsedTime.setBounds(width + left * 2, 270, 300, 25);
        this.add(labelUsedTime);

        labelBestLength = new JLabel("最佳路长：");
        labelBestLength.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelBestLength.setBounds(width + left * 2, 300, 300, 25);
        this.add(labelBestLength);

        //======================================================================
        labelMessageShow = new JLabel("消息提示");
        labelMessageShow.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelMessageShow.setBounds(width + left * 2 + 40, 340, 300, 25);
        this.add(labelMessageShow);

        labelMessage = new JLabel("");
        labelMessage.setFont(new Font("HYQingYaTiJ", Font.BOLD, 15));
        labelMessage.setForeground(Color.red);
        labelMessage.setBounds(width + left * 2, 370, 300, 25);
        this.add(labelMessage);

        //======================================================================
        buttonCalculation = new JButton("计 算");
        buttonCalculation.setBounds(width + left * 2 + 40, 450, 100, 25);
        this.add(buttonCalculation);
        buttonCalculation.addActionListener(this);// 为查询按钮注册监听器

        this.setVisible(true);// 设置窗体可见


    }

    /**
     * 事件处理
     * @param e
     */
    @Override
    public void actionPerformed(ActionEvent e) {

        if (e.getSource() == buttonCalculation) {

            int id = boxStartCity.getSelectedIndex();
            String speed = textSpeed.getText();
            String initTp = testInitTp.getText();
            String minsTp = testlMinsTp.getText();
            String iteratio = textIteration.getText();

            if (!speed.isEmpty() && !initTp.isEmpty() && !minsTp.isEmpty() && !iteratio.isEmpty()) {
                double a = Double.parseDouble(speed);
                double b = Double.parseDouble(initTp);
                double c = Double.parseDouble(minsTp);
                double d = Double.parseDouble(iteratio);

                long startTime = System.currentTimeMillis();
                SA sa = new SA(city, id, a, b, c, d);
                sa.solve();
                long endTime = System.currentTimeMillis();

                bestPath = sa.getBestPath();
                bestLength = sa.getBestLength();
                isDrawLine = true;

                labelUsedTime.setText("计算用时：" + (endTime - startTime) + "ms");
                labelBestLength.setText("最佳路长：" + bestLength + "km");
                showMessage("程序计算成功！");

                repaint();

            } else {
                showMessage("参数不能为空！");
            }
        }
    }

    /**
     * 绘图函数
     * @param g
     */
    public void paint(Graphics g) {
        super.paint(g);
        g.drawImage(image, left, top, width, height, this);
        g.setColor(Color.black);

//        g.setFont(new Font("HYQingYaTiJ", Font.BOLD, 12));
//        for (int i = 0; i < x.length; i++) {
//            // 绘制第i条竖直线
//            g.setColor(Color.red);
//            g.fillOval((int) (x[i] / zoom + left), (int) (y[i] / zoom + top), 5, 5);
//
//            g.setColor(Color.blue);
//            g.drawString(n[i] + "", (int) (x[i] / zoom + left), (int) (y[i] / zoom + top));
//        }

        if (isDrawLine) {

            for (int i = 0; i < bestPath.length; i++) {

                int CurrCityNum = bestPath[i % x.length];
                int NextCityNum = bestPath[(i + 1) % x.length];

                int CurrX = (int) (x[CurrCityNum] / zoom + left);
                int CurrY = (int) (y[CurrCityNum] / zoom + top);

                int NextX = (int) (x[NextCityNum] / zoom + left);
                int NextY = (int) (y[NextCityNum] / zoom + top);

                g.drawLine((int) CurrX, CurrY, NextX, NextY);

                g.drawString("(" + (i + 1) + ") " + distance[CurrCityNum][NextCityNum] + "km", (int) (NextX + (CurrX - NextX) / 2), (int) (NextY + (CurrY - NextY) / 2));

                try {
                    Thread.sleep(400);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }

    }

    /**
     * 显示提示消息
     * @param message
     */
    public void showMessage(String message) {
        labelMessage.setText(message);
    }


    public static void main(String[] args) {
        City city = new City("resource/data.json");
        new TspFrame(city);
    }
}
